package com.gitee.grassprogramming.orm.base;

import com.gitee.grassprogramming.orm.design.BaseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Component;
import com.gitee.grassprogramming.orm.annotation.TraceMethod;
import com.gitee.grassprogramming.orm.util.MapperUtil;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by paul on 2019/1/1.
 */
@Component
public class Command {
    private JdbcTemplate jdbcTemplate;
    private MapperUtil mapperUtil;
    private DriverManagerDataSource dataSource;
    private boolean traceSQL;

    public Command(){
        mapperUtil = new MapperUtil();
        traceSQL = false;
    }

    private String SQLText;
    private List<Object> SQLParams;

    @TraceMethod
    public Boolean executeCommand(){
        if(null!=dataSource){
            jdbcTemplate = Config.GetInstance().getJdbcTemplate(dataSource);
        }
        int result=0;
        if(SQLParams.size()>0){
            result = jdbcTemplate.update(SQLText,SQLParams.toArray());
        }else{
            result = jdbcTemplate.update(SQLText);
        }
        if(result>0){
            return true;
        }else{
            return  false;
        }
    }

    public SqlRowSet executeScarCommand(){
        if(null!=dataSource){
            jdbcTemplate = Config.GetInstance().getJdbcTemplate(dataSource);
        }
        return jdbcTemplate.queryForRowSet(SQLText,SQLParams.toArray());
    }

    @TraceMethod
    public <T extends BaseEntity> T queryCommand(Class<T> tClass) throws Exception{
        if(null!=dataSource){
            jdbcTemplate = Config.GetInstance().getJdbcTemplate(dataSource);
        }
        T obj = tClass.newInstance();
        Map<String, Object> result;
        if(SQLParams.size()>0){
            result =jdbcTemplate.queryForMap(SQLText,SQLParams.toArray());
        }else{
            result =jdbcTemplate.queryForMap(SQLText);
        }
        try {
            List<Field> fs = mapperUtil.GetMapperFields(tClass);
            for (Field f:fs) {
                f.setAccessible(true);
                f.set(obj,result.get(f.getName()));
            }
        }catch (Exception e){
            System.out.println(e.getStackTrace());
            throw  e;
        }finally {
            return obj;
        }
    }

    @TraceMethod
    public <T extends BaseEntity> List<T> queryListCommand(Class<T> tClass) throws Exception{
        if(null!=dataSource){
            jdbcTemplate = Config.GetInstance().getJdbcTemplate(dataSource);
        }
        List<T> resultlist = new ArrayList<T>();
        List<Map<String, Object>> result;
        if(SQLParams.size()>0){
             result =jdbcTemplate.queryForList(SQLText,SQLParams.toArray());
        }else{
            result =jdbcTemplate.queryForList(SQLText);
        }
        try {
            List<Field> fs = mapperUtil.GetMapperFields(tClass);
            for (Map<String,Object> m:result) {
                T obj = tClass.newInstance();
                for (Field f:fs) {
                    f.setAccessible(true);
                    f.set(obj,m.get(f.getName()));
                }
                resultlist.add(obj);
            }
        }catch (Exception e){
            System.out.println(e.getStackTrace());
            throw  e;
        }finally {
            return resultlist;
        }
    }

    @TraceMethod
    public List<Map<String,Object>> queryViewCommand(){
        if(null!=dataSource){
            jdbcTemplate = Config.GetInstance().getJdbcTemplate(dataSource);
        }
        return jdbcTemplate.queryForList(SQLText,SQLParams.toArray());
    }

    public String getSQLText() {
        return SQLText;
    }

    public void setSQLText(String SQLText) {
        this.SQLText = SQLText;
    }

    public List<Object> getSQLParams() {
        return SQLParams;
    }

    public void setSQLParams(List<Object> SQLParams) {
        this.SQLParams = SQLParams;
    }

    public boolean isTraceSQL() {
        return traceSQL;
    }

    public void setTraceSQL(boolean traceSQL) {
        this.traceSQL = traceSQL;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public DriverManagerDataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DriverManagerDataSource dataSource) {
        this.dataSource = dataSource;
    }
}
